#ifdef __cplusplus
    #include <cstdlib>
#else
    #include <stdlib.h>
#endif
#define MAXWIDTH 640

#define MAXHEIGHT 480

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
//#include "tinyxml2.h"
#include "NLTmxMap.h"
#include <iostream>
#include "Player.h"
#include "GameMap.h"
#include <guichan.hpp>
#include <guichan/sdl.hpp>
typedef enum TILE_LIST {
    T_GRASS = 1,
    T_SAND,
    T_WATER
} TILE_LIST;
typedef enum DIRECTIONS {
    UP = 273,
    DOWN,
    RIGHT,
    LEFT
} DIRECTIONS;
//static void* loadfile(const char * filename, bool appendNull);


static void* loadFile( const char * filename, bool appendNull ) {

    FILE* f = fopen( filename, "r" );
    if ( !f ) {
        return 0;
    }

    fseek( f, 0, SEEK_END );
    auto length = ftell( f ) + appendNull;
    fseek( f, 0, SEEK_SET );

    void* buffer = malloc( length );
    fread( buffer, length, 1, f );
    fclose( f );

    if ( appendNull ) {
        ((char*)buffer)[ length-1 ] = 0;
    }

    return buffer;
}
void draw_player(SDL_Surface* background, SDL_Rect dest);
SDL_Surface* draw_map(SDL_Surface* background, NLTmxMap* map_data);
SDL_Surface* image_load(std::string file_name);

SDL_Surface* image_load(std::string file_name) {
    SDL_Surface* loaded = NULL;
    SDL_Surface* optoed = NULL;
    loaded = IMG_Load(file_name.c_str());
    if(loaded != NULL) {
        optoed = SDL_DisplayFormatAlpha(loaded);
        SDL_FreeSurface(loaded);
    }
    return optoed;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
    //Temporary rectangle to hold the offsets
    SDL_Rect offset;

    //Get the offsets
    offset.x = x;
    offset.y = y;

    //Blit the surface
    SDL_BlitSurface( source, NULL, destination, &offset );
}

int main ( int argc, char** argv )
{
    gcn::SDLInput* input;             // Input driver
    gcn::SDLGraphics* graphics;       // Graphics driver
    gcn::SDLImageLoader* imageLoader; // loading images
    gcn::Gui* gui;            // A Gui object - binds it all together
    gcn::Container* top;      // A top container
    gcn::ImageFont* font;     // A font
    gcn::Label* label;        // And a label for the Hello World text

    char * tmx_map = (char*) loadFile( "untitled.tmx", true );
    std::cout << UP << DOWN << RIGHT << LEFT << endl;
    //tinyxml2::XMLDocument xdoc;
    //xdoc.LoadFile("untitled.tmx");
    NLTmxMap* map1;
    map1 = NLLoadTmxMap( tmx_map );
    GameMap testmap;
    testmap.print();
    //SDL_WM_SetIcon(IMG_Load("down1.png"), NULL);
    // std::cout << testmap.get_tile_data(0,27) << endl << endl;
    std::cout << map1->tilesets[2]->filename << endl;

//    NL
//    map1->layers(0).data[0];
   // std::cout << map1->width << " x " << map1->height << std::endl;

    //std::cout <<    map1->layers[0]->data[0] << endl;
//    int index = 0;
//    for(int i = 0; i < 32; i++) {
//        for(int j = 0; j < 24; j++) {
//            std::cout << map1->layers[0]->data[index];
//            index++;
//            index % 32 == 0 ? std::cout << " " << index << std::endl : std::cout << " ";
//
//        }
//
//    }
//    index = 0;

  //  delete map1;
//    XMLDocument xdoc;
    // initialize SDL video
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "Unable to init SDL: %s\n", SDL_GetError() );
        return 1;
    }

    // make sure SDL cleans up before exit
    atexit(SDL_Quit);
    SDL_WM_SetCaption( "Leaky Cunt", NULL );
    SDL_WM_SetIcon(SDL_LoadBMP("Fire.bmp"),NULL);
    // create a new window
    SDL_Surface* screen = SDL_SetVideoMode(MAXWIDTH, MAXHEIGHT, 8,
                                           SDL_SWSURFACE|SDL_DOUBLEBUF);


    if ( !screen )
    {
        printf("Unable to set 640x480 video: %s\n", SDL_GetError());
        return 1;
    }


    // centre the bitmap on screen
    SDL_Rect dstrect;
    SDL_Rect tilerect;
    dstrect.x = 0;
    dstrect.y = 0;
    tilerect.x = 0;
    tilerect.y = 0;

    int counter = 0;
    // program main loop
    bool done = false;
    bool draw_map_done = false;
    Player fuck(20, 0, 20, 20, "down1.png");
    //draw_map(screen, map1);
    testmap.draw(screen);
    SDL_Surface* bgtmp = NULL;
    bgtmp = SDL_LoadBMP("background.bmp");
    while (!done){
   // message processing loop
        SDL_Event event;
        while (SDL_PollEvent(&event)){
            // check for messages
            switch (event.type){
                // exit if the window is closed
                case SDL_QUIT:
                    done = true;
                    break;

                    // check for keypresses
                case SDL_KEYDOWN:

                    counter++;
                // exit if ESCAPE is pressed
                    switch (event.key.keysym.sym) {
                        case SDLK_RIGHT:
                            fuck.Move(RIGHT, screen);
                            break;

                        case SDLK_LEFT:
                            fuck.Move(LEFT, screen);
                            break;

                        case SDLK_UP:
                            fuck.Move(UP, screen);
                            break;

                        case SDLK_DOWN:
                            fuck.Move(DOWN, screen);
                            break;

                        case SDLK_ESCAPE:
                            done = true;
                            break;
                        default: break;
                    } // end key symbol switch
                    break;

            } // end event switch
        } // end of message processing

        // DRAWING STARTS HERE

        // clear screen
        SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
        SDL_BlitSurface(bgtmp, 0, screen, 0);
        // draw bitmap
        //SDL_BlitSurface(background, NULL, screen, NULL);
        //fuck.Draw(screen);
        //testmap.draw(screen);

        fuck.Draw(screen);
       // SDL_BlitSurface(bmp, 0, screen, &dstrect);

        // DRAWING ENDS HERE
        //fuck.Clean();
        // finally, update the screen :)
        //SDL_Flip(screen);
        SDL_Flip(screen);
    } // end main loop
    fuck.Clean();
    // free loaded bitmap
    delete map1;
   // SDL_FreeSurface(bmp);
    //SDL_FreeSurface(background);
    SDL_FreeSurface(bgtmp);
    SDL_FreeSurface(screen);
    // all is well ;)
    printf("Exited cleanly\n");
    return 0;
}

SDL_Surface* draw_map(SDL_Surface* screen, NLTmxMap* map_data) {
    int index = 0;

    SDL_Surface* bkgr = NULL;
   // SDL_Surface* surf_return = NULL;
    //SDL_Surface* opto = NULL;

    SDL_Rect offset;
    offset.x = 0;
    offset.y = 0;

    for(int i = 0; i < 24; i++) {

        for(int j = 0; j < 32; j++) {
            switch(map_data->layers[0]->data[index]) {
                case T_GRASS:
                    bkgr = image_load(map_data->tilesets[T_GRASS-1]->filename.c_str());
                    break;
                case T_SAND:
                    bkgr = image_load(map_data->tilesets[T_SAND-1]->filename.c_str());
                    break;
                case T_WATER:
                    bkgr = image_load(map_data->tilesets[T_WATER-1]->filename.c_str());
                    break;
                default:
                    bkgr = image_load("grass.png");
                    break;

            }
       //     opto = SDL_DisplayFormat(bkgr);
          //  SDL_FreeSurface(bkgr);
            SDL_BlitSurface(bkgr,NULL,screen,&offset);
            offset.x += 20;
            index++;
        }
        offset.y += 20;
        offset.x = 0;

    }
    //screen = SDL_DisplayFormat(bkgr);
    offset.x=0;offset.y=0;
    SDL_FreeSurface(bkgr);
   // SDL_FreeSurface(opto);

    return screen;
//    SDL_FreeSurface(bkgr);
}
